package pikasial.fs;

import java.io.File;
import javax.swing.filechooser.FileSystemView;

/**
 * Representation des éléments du système de fichiers importés dans Pikasial.
 *
 * @author ESIAL - Groupe 14
 * @see pikasial.fs.PikasialFS
 * @see pikasial.fs.Dossier
 * @see pikasial.fs.Fichier
 */
public abstract class FSElement {

    /** Le nom (pas le chemin) de l'élement. */
    protected String name;
    /** Le chemin du dossier parent (null si c'est une racine). */
    protected String parent;
    /** Le chemin abstrait (au sens de la classe File) vers le fichier. */
    protected File file;
    /** Le chemin de l'élément dans le système de fichiers */
    protected String path;

    /**
     * Crée un élement à partir de son chemin abstrait.
     *
     * @param f - chemin abstrait de l'élément
     */
    protected FSElement(final File f) {
        file = f;
        name = f.getName();
        parent = f.getParent();
        path = f.getPath();
    }

    /**
     * Crée un élement à partir du chemin spécifié.
     *
     * @param path - le chemin de l'élement
     */
    protected FSElement(final String path) {
        this(new File(path));
    }

    /**
     * Crée un élement dans le dossier (si le parent est un fichier,
     * ça n'a aucun sens) de chemin spécifié et portant le nom spécifié.
     *
     * @param cheminParent - le chemin du dossier parent
     * @param nameChild - le nom de l'element
     */
    protected FSElement(final String cheminParent, final String nameChild) {
        parent = cheminParent;
        name = nameChild;
        file = new File(parent, name);
    }

    /**
     * Teste si cet élement contient des images.
     *
     * @return true si l'élement est un dossier
     * et contient des images, faux sinon
     */
    public abstract boolean containsImage();

    /**
     * Compare cet élement avec l'objet passé en paramètre.
     * <p>
     * La comparaison se fait en fonction du chemin vers l'élement:
     * 2 élements qui ont le même chemin sur le disque sont égaux.
     *
     * @param other - l'objet à comparer avec l'instance courante
     * @return true si les 2 objets sont égaux, false sinon
     * @see java.lang.Object#equals(java.lang.Object)
     */
    @Override
    public final boolean equals(final Object other) {
        if ((other != null) && (other instanceof FSElement)) {
            return file.getPath().equals(
                ((FSElement) other).getJavaFile().getPath());
        } else {
            return false;
        }
    }

    /**
     * Retourne le chemin abstrait vers l'élement.
     *
     * @return chemin abstrait de l'élement (instance de java.io.File)
     * @see java.io.File
     */
    public final File getJavaFile() {
        return file;
    }

    /**
     * Retourne le nom de l'élement.
     *
     * @return le nom de l'element
     * @see #toString()
     */
    public final String getName() {
        return name;
    }

    /**
     * Renvoie le chemin de l'élément dans le système de fichiers.
     * @return le chemin de l'élément.
     */
    public String getPath() {
        return path;
    }

    /**
     * Retourne l'empreinte de cette instance.
     * <p>
     * L'empreinte retournée est égale à celle de la chaîne de caractère
     * correspondant au chemin (deux objets égaux selon equals()
     * doivent retourner le même "hash code").
     * Cette méthode doit être redéfinie quand on redéfinit equals().
     *
     * @return l'empreinte de cet élement
     * @see java.lang.Object#hashCode()
     */
    @Override
    public final int hashCode() {
        return file.getPath().hashCode();
    }

    /**
     * Teste si cet élement est un dossier.
     *
     * @return true si l'élement est un dossier, false si c'est un fichier
     */
    public abstract boolean isDirectory();

    /**
     * Retourne une représentation de l'élement sous forme de chaîne
     * de caractères.
     * <p>
     * En fait, retourne le nom de l'élement.
     * @return la chaîne de caractères représentant l'élement
     * @see #getName()
     */
    @Override
    public String toString() {
        if (file.getParent() == null) {
            return FileSystemView.getFileSystemView().getSystemDisplayName(file);
        }
        return getName();
    }
}
